﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;
using dahtd4ever.GameScreens;

namespace dahtd4ever.GameScreens
{
    public class GameScreen
    {
        HUD hud;

        public TileMap map;
        public TileMap getMap() { return this.map; }

        List<Enemy> activeEnemies;
        List<Tower> activeTowers;
        public List<Geschoss> activeGeschosse;

        public int actualLevel = 1;
        public int actualWave = 1;
        int enemyCounter = 0;

        SoundEffect shot;
        SoundEffect death;
        SoundEffect hit;

        public void nextWave()
        {
            if (actualWave < this.levelManager.getLevels()[actualLevel].getWaves().Count)
            {
                actualWave++;
                enemyCounter = 0;
            }
        }

        TimeSpan enemySpawnTime;
        TimeSpan previousSpawnTime;

        public LevelManager levelManager;
        public Level level;

        Texture2D blackpx;
        Animation deathAnim;
        Game1 game;

        public GameScreen(Game1 game)
        {
            this.game = game;

            newGame();
            
            deathAnim = new Animation();
            deathAnim.Initialize(game.Content.Load<Texture2D>("Graphics/explosion"), Vector2.Zero, 134, 134, 12, 100, Color.White, 0.5f, false);
            deathAnim.Active = false;
            blackpx = game.Content.Load<Texture2D>("Graphics/blackpx");        

            death = game.Content.Load<SoundEffect>("Sound\\162792__timgormly__8-bit-explosion1");
            //shot = game.Content.Load<SoundEffect>("Sound\\Cannon");
            hit = game.Content.Load<SoundEffect>("Sound\\hit8bit");
        }

        public void reset() {
            newGame();
        
        }

        public void newGame()
        {
            
            actualWave = 1;
            enemyCounter = 0;

            // Levelmanager 
            levelManager = new LevelManager();
            levelManager.Init();
            levelManager.readInLevels(2);
            level = levelManager.getLevels()[actualLevel - 1];

            // Initialize the enemies list
            activeEnemies = new List<Enemy>();

            // Initialize the enemies list
            activeTowers = new List<Tower>();

            // Set the time keepers to zero
            previousSpawnTime = TimeSpan.Zero;

            // Used to determine how fast enemy respawns
            enemySpawnTime = TimeSpan.FromSeconds(levelManager.getLevels()[actualLevel - 1].getEnemySpawnTime());

            //erzeugt neue Map und übergibt der Map einen eigenen Content-Manager zum laden der Tilegrafiken
            map = new TileMap();
            map.Init(game.Content);
            map.Load("Maps/Map01.map");

            // Meldet HUD und input als Game-Component an
            hud = new HUD(map, game.Content, levelManager.getLevels()[actualLevel - 1], this);

            // geschosse
            activeGeschosse = new List<Geschoss>();
        }

        public void Update(GameTime gameTime)
        {
            UpdateEnemies(gameTime);
            UpdateTowers(gameTime);
            UpdateGeschosse(gameTime);
            hud.Update(levelManager.getLevels()[actualLevel - 1], game, gameTime);
            deathAnim.Update(gameTime);

            if (ScreenManager.keyboard.IsNewKeyPress(Keys.Escape))
            {
                ScreenManager.gameState = GameState.Pause;
                ScreenManager.lastState = GameState.Play;
            }
        }

        // Liest die Gegnerfolge aus den Wellen ein
        private int getTypeFromWave()
        {
            // Ansonsten den Gegnertyp iterativ aus der Welle wiedergeben
            if (enemyCounter < levelManager.getLevels()[actualLevel - 1].getWaves()[actualWave - 1].getEnemyCount())
            {
                int x = levelManager.getLevels()[actualLevel - 1].getWaves()[actualWave - 1].getEnemies()[enemyCounter];
                enemyCounter++;
                return x;
            }
            else return 0;
        }

        // Fügt einen Gegner hinzu
        private void AddEnemy()
        {
            Enemy enemy = new Enemy(map, getTypeFromWave(), game);
            enemy.Initialize(game.Content);
            enemy.LoadContent();
            activeEnemies.Add(enemy);
        }

        // Fügt einen Tower hinzu
        public void AddTower(int type, Vector2 position)
        {
            Tower tower = new Tower(map, type, position);
            tower.Initialize(game.Content);
            tower.LoadContent();
            activeTowers.Add(tower);
        }

        private void UpdateEnemies(GameTime gameTime)
        {
            // Spawn a new enemy enemy every 1.5 seconds
            if (gameTime.TotalGameTime - previousSpawnTime > enemySpawnTime)
            {
                previousSpawnTime = gameTime.TotalGameTime;

                // Add an Enemy - bis Wellengrenze erreicht
                if (levelManager.getLevels()[actualLevel - 1].getWaves()[actualWave - 1].getEnemyCount() > enemyCounter)
                {
                    AddEnemy();
                }
            }

            // Update the Enemies
            for (int i = activeEnemies.Count - 1; i >= 0; i--)
            {
                // Tod abchecken und Maßnahmen einleiten :)
                if (activeEnemies[i].getHp() <= 0)
                {
                    activeEnemies[i].Inactive();

                    // ANIMATIoN hier einfügen
                    //folgend wird der Ressourcenvorrat um den Gegnerwert erhöht
                    deathAnim = new Animation();
                    deathAnim.Initialize(game.Content.Load<Texture2D>("Graphics/explosion"), Vector2.Zero, 134, 134, 10, 100, Color.White, 0.6f, false);
                    Rectangle enemyBound = activeEnemies[i].getBoundarie();
                    deathAnim.Position = new Vector2(enemyBound.X + enemyBound.Width / 2, enemyBound.Y + enemyBound.Height / 2);
                    deathAnim.Active = true;
                    death.Play();

                    float newRes = levelManager.getLevels()[actualLevel - 1].getResources() + activeEnemies[i].getResourcesByDeath();
                    levelManager.getLevels()[actualLevel - 1].setResources(newRes);
                }
                // Durchkommen abchecken
                if (activeEnemies[i].getPosition().X > map.GetWidth() * map.getTileWidth())
                {
                    activeEnemies[i].Inactive();
                    float newLife = levelManager.getLevels()[actualLevel - 1].getPlayersLife() - activeEnemies[i].getLifelossByWalktrough();
                    levelManager.getLevels()[actualLevel - 1].setPlayersLife(newLife);
                }

                if (activeEnemies[i].Active() == false)
                {
                    activeEnemies.RemoveAt(i);
                }
                else { activeEnemies[i].Update(gameTime); }
                // Wenn keine Gegner mehr und alle Gegner gespawnt: Welle inaktiv setzen
                if (activeEnemies.Count == 0 && enemyCounter == levelManager.getLevels()[actualLevel - 1].getWaves()[actualWave - 1].getEnemyCount()) { levelManager.getLevels()[actualLevel - 1].getWaves()[actualWave - 1].setInactive(); }

            }
        }

        private void UpdateTowers(GameTime gt)
        {
            for (int i = 0; i < activeTowers.Count; i++)
            {
                if (activeTowers[i].checkIfAttack(gt) && activeTowers[i].ifEnemiesInRange(activeEnemies, activeTowers[i].rangeRectangle))
                {
                    hit.Play();
                    Enemy enemyToAttack = activeTowers[i].enemiesInRange(activeEnemies, activeTowers[i].rangeRectangle)[0];
                    activeTowers[i].attackEnemy(enemyToAttack, activeEnemies);
                    activeGeschosse.Add(new Geschoss(new Vector2(activeTowers[i].boundarie.X + (activeTowers[i].boundarie.Width / 2), activeTowers[i].boundarie.Y + (activeTowers[i].boundarie.Height / 2)), new Vector2(enemyToAttack.getBoundarie().X + (enemyToAttack.getBoundarie().Width / 2), enemyToAttack.getBoundarie().Y + (enemyToAttack.getBoundarie().Height / 2)), game.Content));
                }
            }
        }

        private void UpdateGeschosse(GameTime gt)
        {
            for (int i = 0; i < activeGeschosse.Count; i++)
            {
                activeGeschosse[i].Update();
                if (!activeGeschosse[i].active) {
                    deathAnim = new Animation();
                    deathAnim.Initialize(game.Content.Load<Texture2D>("Graphics/explosion"), new Vector2(activeGeschosse[i].boundarie.X + activeGeschosse[i].boundarie.Width / 2, activeGeschosse[i].boundarie.Y + activeGeschosse[i].boundarie.Height / 2), 134, 134, 3, 100, Color.White, 0.2f, false);
                    activeGeschosse.RemoveAt(i);
                }
            }
        }

        public void Draw()
        {
            game.spriteBatch.Begin();

            map.Draw(game.spriteBatch);
            //gegner zeichnen
            for (int i = 0; i < activeEnemies.Count; i++) { activeEnemies[i].Draw(game.spriteBatch); }
            //tower zeichnen
            for (int i = 0; i < activeTowers.Count; i++) { activeTowers[i].Draw(game.spriteBatch); }
            // Geschosse malen
            for (int i = 0; i < activeGeschosse.Count; i++) { activeGeschosse[i].Draw(game.spriteBatch); }
            // HUD zeichnen
            hud.Draw(game.spriteBatch, game.font2, levelManager.getLevels()[actualLevel - 1], game);
            //Leben und Geld zeichnen
            game.spriteBatch.DrawString(game.font2, Convert.ToString(levelManager.getLevels()[actualLevel - 1].getPlayersLife()), new Vector2(750, 400), Color.White);
            game.spriteBatch.DrawString(game.font2, Convert.ToString(levelManager.getLevels()[actualLevel - 1].getResources()), new Vector2(625, 400), Color.White);
            // Maus zeichnen

            deathAnim.Draw(game.spriteBatch);

            game.spriteBatch.End();
        }
    }
}
